<template>
  <div class="page-table-container">
    <a-table
      class="page-table"
      :dataSource="dataRef"
      :columns="columns"
      :pagination="false"
      v-bind="$attrs"
      :rowKey="rowKey"
      :row-selection="
        isSelection
          ? { selectedRowKeys: checkedRowkeys, onChange: selectionChange }
          : null
      "
    >
      <template #bodyCell="{ column, record, index }">
        <template v-if="column.key === 'operate'">
          <span
            v-for="(item, i) in column.btns"
            :key="i"
            :class="item.class"
            @click="handelOperate(item, record)"
            ><i v-if="item.icon" :class="item.icon"></i> {{ item.label }}</span
          >
        </template>
        <template v-if="column.key === 'serial'">
          <span>{{ index + 1 }}</span>
        </template>
        <template v-if="column.render">
          <span>{{ column.render(record) }}</span>
        </template>
        <slot v-if="column.slotName" :name="column.slotName" :record="record" />
      </template>
    </a-table>
    <div class="page-table-pagination" v-if="pagination.show">
      <a-pagination
        :current="paginationReactive.pageIndex"
        :total="paginationReactive.pageTotal"
        :show-quick-jumper="pagination.showQuickJumper"
        :show-size-changer="pagination.showSizeChanger"
        @change="change"
      />
    </div>
  </div>
</template>
<script setup>
import store from "@/store";
const emit = defineEmits();
const props = defineProps({
  id: {
    type: String,
    default: "",
  },
  isSelection: {
    type: Boolean,
    default: false,
  },
  data: {
    type: [Array, Function],
    default: () => [],
  },
  rowKey: {
    type: String,
    default: "id",
  },
  columns: {
    type: Array,
    default: () => [],
  },
  pagination: {
    type: Object,
    default: () => {
      return {
        show: true,
        limit: 10,
        pageIndex: 1,
        showQuickJumper: true,
        showSizeChanger: true,
      };
    },
  },
});

const exportData = ref([]);

/**
 * 处理操作事件。
 *
 * 该函数用于触发一个名为'handelOperate'的自定义事件，携带操作类型和相关行数据。
 * 主要用于在表格或其他组件中进行行级操作，如编辑、删除、查看详情等。
 *
 * @param {string} type - 操作类型。代表了将要执行的具体操作，如'edit'、'delete'等。
 * @param {object} row - 行数据。包含与操作相关的具体数据信息。
 * @returns {void} 该函数不返回任何值。
 */
const handelOperate = (obj, row) => {
  emit("operateChange", obj, row);
};

// 初始化分页反应式对象
const paginationReactive = reactive({
  pageCount: 0,
  pageTotal: 0,
  limit: props.pagination.limit || 10,
  pageIndex: props.pagination.page || 1,
});

// 数据源引用
const dataRef = ref([]);
// 加载状态引用
const loadingRef = ref(false);
// 选中行键引用
const checkedRowkeys = ref([]);

/**
 * 异步查询数据。
 * @returns {Promise} 返回数据Promise。
 */
const query = () => {
  return new Promise((resolve, reject) => {
    if (props.data instanceof Array) {
      resolve({
        list: props.data,
      });
    } else if (props.data instanceof Function) {
      const formData = store.state.app.formSearchData[props.id] || {};
      const paper = {};
      paper[rescf.pageIndex] = paginationReactive.pageIndex;
      paper[rescf.limit] = paginationReactive.limit;
      const params = Object.assign(
        {},
        props.pagination.show ? paper : {},
        formData
      );
      props
        .data(params)
        .then((res) => {
          if (res.code === rescf.codeVal) {
            const pageTotal = (res.total || res.data.total || 0) * 1;
            const pageCount = Math.ceil(
              pageTotal / paginationReactive.limit
            );
            resolve({
              list: res.data ? res.data.list || res.data : [],
              pageCount: pageCount,
              pageTotal: pageTotal,
              pageIndex: params[rescf.pageIndex],
              limit: params[rescf.limit],
            });
          }
        })
        .catch((e) => {
          reject(e.message || "调用失败");
        });
    }
  });
};

/**
 * 异步加载数据列表。
 */
const queryList = async () => {
  loadingRef.value = true;
  try {
    const res = await query();
    dataRef.value = res.list;
    loadingRef.value = false;
    emit("queryDataChange", dataRef.value);
    if (props.pagination) {
      paginationReactive.pageCount = res.pageCount;
      paginationReactive.pageTotal = res.pageTotal;

      const page = Math.floor(
        paginationReactive.pageTotal / paginationReactive.limit
      );
      if (
        paginationReactive.pageTotal > 0 &&
        paginationReactive.pageTotal % paginationReactive.limit === 0 &&
        paginationReactive.pageIndex > page
      ) {
        paginationReactive.pageIndex =
          paginationReactive.pageTotal / paginationReactive.limit;
        queryList();
      }
    }
  } catch (error) {
    console.log("errprrr======", error);
    loadingRef.value = false;
  }
};

/**
 * 刷新数据列表。
 */
const refleshList = async () => {
  const res = await query();
  dataRef.value = res.list || res;
};

/**
 * 分页或每页项数改变时的处理函数。
 * @param {number} page 当前页码。
 * @param {number} limit 每页项数。
 */
const change = (page, limit) => {
  paginationReactive.pageIndex = page;
  paginationReactive.limit = limit;
  queryList();
};

/**
 * 设置全部行的选中状态。
 * @param {boolean} val 是否选中所有行。
 */
const setChecked = (val) => {
  if (val) {
    checkedRowkeys.value = dataRef.value.map((a) => a[props.rowKey]);
  } else {
    checkedRowkeys.value = [];
  }
  emit("selectionChange", checkedRowkeys.value);
};

/**
 * 选中项变化时的处理函数。
 * @param {Array} keys 选中项的键值集合。
 */
const selectionChange = (keys, row) => {
  checkedRowkeys.value = keys;
  exportData.value = row;
  emit("selectionChange", keys, row);
};

/**
 * 清空选中行的键值。
 */
const clearCheckedRowkeys = () => {
  checkedRowkeys.value = [];
};

/**
 * 根据给定的ID集合设置行的选中状态。
 * @param {Array} ids ID集合。
 * @param {string} key 行标识键名。
 */
const setSelection = (ids, key) => {
  dataRef.value.forEach((a) => {
    if (ids.includes(a[key])) {
      a.checked = true;
    }
  });
};

const getData = () => {
  const data = exportData.value.length ? exportData.value : dataRef.value;
  return data;
};

// 重新加载数据
const fetchData = () => {
  paginationReactive.pageIndex = 1;
  queryList();
}

// 页面挂载时加载数据
onMounted(() => {
  queryList();
});

// 把相关方法暴露给外部使用
defineExpose({
  setChecked,
  refleshList,
  getData,
  fetchData,
  queryList,
  setSelection,
  clearCheckedRowkeys,
});
</script>
<style lang="scss" scoped>
.page-table-container {
  flex: 1;
  // height: calc(100% - 132px);
  position: relative;
  min-height: 310px;
  .page-table {
    max-height: calc(100% - 72px);
    overflow-y: auto;
    position: absolute;
    width: 100%;
  }
}
.page-table-pagination {
  padding: 20px 0;
  display: flex;
  justify-content: flex-start;
  position: absolute;
  width: 100%;
  bottom: 0;
  ul.ant-pagination {
    display: inline-block;
  }
}
</style>
